package com.yc.service.impl;

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yc.common.secure.support.SecureAuthenticationProvider;
import com.yc.common.utils.Encrypt;
import com.yc.entity.StudentInfo;
import com.yc.entity.User;
import com.yc.entity.WxUser;
import com.yc.mapper.AttendanceMapper;
import com.yc.mapper.ClassInfoMapper;
import com.yc.mapper.StudentInfoMapper;
import com.yc.mapper.UserMapper;
import com.yc.service.UserService;
import com.yc.service.WxUserService;
import com.yc.vo.AttendanceData;
import com.yc.vo.Result;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestParam;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author mqm
 * @version 1.0
 * @date 2023/7/11 20:34
 */
@Service
public class WxUserServiceImpl implements WxUserService {

    @Resource
    private UserService userService;
    @Resource
    private StudentInfoServiceImpl studentInfoService;
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private UserMapper userMapper;
    @Value("${WeChat-duplicate-binding.inspect}")
    private boolean inspect;
    @Value("${WeChat-duplicate-binding.APPID}")
    private  String appid;
    @Value("${WeChat-duplicate-binding.SECRET}")
    private  String secret;
    @Resource
    private ClassInfoMapper classInfoMapper;
    @Resource
    private AttendanceMapper attendanceMapper;
    @Resource
    private WxUser wxUser;
    @Resource
    private StudentInfoMapper studentInfoMapper;

    /**
     * 生成请求 openid 连接
     * @param code
     * @return
     */
    public String getWX_URL(String code){
        //微信官方提供获取openid的url
        String WX_URL = "https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code";
        //替换appid，appsecret，和code
        String requestUrl = WX_URL.replace("APPID",appid)
                .replace("SECRET", secret)
                .replace("JSCODE", code);
        return requestUrl;
    }


    /**
     * 微信小程序授权登录
     * @param Appid
     * @param code
     * @param avatarUrl
     * @param nickname
     * @param username
     * @param session_key
     * @param openID
     * @return
     */
    @Override
    public Result WxLogin(String Appid, String code, String avatarUrl, String nickname, String username, String session_key, String openID) {
        if (openID.equals("") || session_key.equals("")) {
            String requestUrl = getWX_URL(code);
            //调用get方法
            JSONObject jsonObject = GetOpenidAndSessionKey(requestUrl);
            //解析返回值，对象解析成字符串
            session_key =jsonObject.getStr("session_key");
            openID = jsonObject.getStr("openid");
        }
        Result result = null;
        Map<String,Object> maps =new HashMap<>();
        if (username.length() == 11) {
            String appid = userMapper.queryAppid(username);

            if (appid == null) {
                if (inspect){
                    int stuCount = userMapper.queryCountByStu(openID);
                    int sysCount = userMapper.queryCountBySys(openID);
                    int count = sysCount+stuCount;
                    if (count >= 1) {
                        return Result.error("用户已被其他账号绑定!");
                    }
                }
                //学生登录
                StudentInfo studentInfo = studentInfoService.selectStuid(username);
                if (studentInfo == null ) {
                    studentInfoService.insertByStuid(openID, avatarUrl, null, username);
                    maps.put("openID",openID);
                    maps.put("session_key",session_key);
                    result = Result.success(maps);
                } else {
                    String openId = studentInfo.getAppid();
                    String wxpic = studentInfo.getWxpic();
                    if (openId.equals("")){
                        studentInfoService.insertByStuid(openID, wxpic, null, username);
                        maps.put("openID",openID);
                        maps.put("session_key",session_key);
                        result = Result.success(maps);
                    } else if (!openID.equals(openId)) {
                        return Result.error( "授权失败,一个人只能绑定一个微信号");
                    } else if (!wxpic.equals(avatarUrl)) {
                        studentInfoService.insertByStuid(openID, wxpic, null, username);
                        maps.put("openID",openID);
                        maps.put("session_key",session_key);
                        result = Result.success(maps);
                    }
                }
            } else {
                if (appid.equals(openID)) {
                    maps.put("openID",openID);
                    maps.put("session_key",session_key);
                    result = Result.success(maps);
                }else {
                    return Result.error("该账号已经绑定!");
                }
            }
        } else if (username.length() == 10 && SecureAuthenticationProvider.status == true ) {
            String appid = userMapper.queryAppid(username);
            if (appid == null) {
                if (inspect){
                    int stuCount = userMapper.queryCountByStu(openID);
                    int sysCount = userMapper.queryCountBySys(openID);
                    int count = sysCount+stuCount;
                    if (count >= 1) {
                        return Result.error("用户已被其他账号绑定!");
                    }
                }
                //学生登录
                StudentInfo studentInfo = studentInfoService.selectStuid(username);
                if (studentInfo == null ) {
                    studentInfoService.insertByStuid(openID, avatarUrl, null, username);
                    maps.put("openID",openID);
                    maps.put("session_key",session_key);
                    result = Result.success(maps);
                } else {
                    String openId = studentInfo.getAppid();
                    String wxpic = studentInfo.getWxpic();
                    if (openId.isEmpty()){
                        studentInfoService.insertByStuid(openID, wxpic, null, username);
                    } else if (!openID.equals(openId)) {
                        return Result.error(0, "授权失败,一个人只能绑定一个微信号");
                    } else if (wxpic.equals(avatarUrl) == false) {
                        studentInfoService.insertByStuid(openID, wxpic, null, username);
                    }
                    maps.put("openID",openID);
                    maps.put("session_key",session_key);
                    result = Result.success(maps);
                }
            } else {
                if (appid.equals(openID)) {
                    maps.put("openID",openID);
                    maps.put("session_key",session_key);
                    result = Result.success(maps);
                }else {
                    return  Result.error("该账号已经绑定!");
                }
            }
        } else if (username.matches("[a-zA-Z0-9]+")) {
            String appid = userMapper.queryAppidByTea(username);
            if (appid==null){
                if (inspect){
                    int stuCount = userMapper.queryCountByStu(openID);
                    int sysCount = userMapper.queryCountBySys(openID);
                    int count = sysCount+stuCount;
                    if (count >= 1) {
                        return Result.error("用户已被其他账号绑定!");
                    }
                }

                User user = userService.selectSysByUsername(username);
                if (user == null ) {
                    userService.insertByusername(openID, avatarUrl, null, username);
                    maps.put("openID",openID);
                    maps.put("session_key",session_key);
                    result = Result.success(maps);
                } else {
                    String openid = user.getAppid();
                    String wxpic = user.getWxpic();
                    if (openid.isEmpty()){
                        userService.insertByusername(openID, avatarUrl, null, username);
                    } else if (!openid.equals(openID)) {
                        return Result.error(0, "授权失败,一个人只能绑定一个微信号");
                    } else if (!wxpic.equals(avatarUrl)) {
                        userMapper.updateBySysWxpic(wxpic, username);
                    }
                    maps.put("openID",openID);
                    maps.put("session_key",session_key);
                    result = Result.success(maps);
                }
            }else {
                if (appid.equals(openID)){
                    maps.put("openID",openID);
                    maps.put("session_key",session_key);
                    result = Result.success(maps);
                }else {
                    return Result.error("该账号已经绑定!");
                }
            }
        } else {
            result = Result.error("请输入正确的用户名密码");
        }
        wxUser.setOpenID(openID);
        wxUser.setSession_key(session_key);
        wxUser.setUsername(username);
        //添加到redis key 为学号
        //WXSESSIONKEY::username
        redisTemplate.opsForHash().put("WXSESSIONKEY::"+username, "session_key",session_key);
        redisTemplate.expire("WXSESSIONKEY::"+username,66, TimeUnit.HOURS);
        return result;
    }


    /**
     * 发起请求生成openid和session_key
     * @param url
     * @return
     */
    public JSONObject GetOpenidAndSessionKey(String url) {
        String body = HttpUtil.createGet(url).execute().body();
        JSONObject jsonObject = JSONUtil.parseObj(body);
        if(Objects.isNull(jsonObject.get("openid"))){
            return null;
        }else{
            return jsonObject;
        }
    }

    /**
     * 密码比对
     * @param stuid
     * @return
     */
    public Result queryPwd(String stuid) {
        String pwd = Encrypt.md5AndSha(stuid);
        String Password = userMapper.queryPwd(stuid);
        if (pwd.equals(Password) == true) {
            return Result.success(0);
        } else {
            return Result.success(1);
        }
    }


    /**
     * 登陆页面的微信授权登录
     */
    public Result wxloginagain( String code){
        String requestUrl = getWX_URL(code);
        //调用get方法
        JSONObject jsonObject = GetOpenidAndSessionKey(requestUrl);
        //解析返回值，对象解析成字符串
        String session_key =jsonObject.getStr("session_key");
        String openID = jsonObject.getStr("openid");
        if (inspect){
            int stuCount = userMapper.queryCountByStu(openID);
            int sysCount = userMapper.queryCountBySys(openID);
            int count = sysCount+stuCount;
            if (count > 1) {
                return Result.error("用户已在其他设备登录!");
            }
        }
        Map<String,Object> map=new HashMap<>();
        //查学生是否绑定了这个openid
        String queryown = userMapper.queryown(openID);
        if (queryown!=null){
            map.put("identity","student");
            map.put("stuid",queryown);
            map.put("session_key",session_key);
            map.put("openId",openID);
            wxUser.setOpenID(openID);
            wxUser.setSession_key(session_key);
            wxUser.setUsername(queryown);
            redisTemplate.opsForHash().put("WXSESSIONKEY::"+queryown, "session_key", session_key);
            redisTemplate.expire("WXSESSIONKEY::"+queryown,66, TimeUnit.HOURS);
            return Result.success(map);
        }else {
            //没有査老师
            Map<String, Object> bysys = userMapper.queryownBysys(openID);
            if (bysys==null){
                return Result.error("该用户未绑定账号");
            }else {
                String username =  (String) bysys.get("username");
                String rolecode = (String) bysys.get("rolecode");
                if (rolecode.contains("COUNSELLOR,TEACHER,LEADER")){
                    map.put("identity","leaderAndTeacher");
                } else if (rolecode.contains("TEACHER,LEADER")){
                    map.put("identity","leaderAndTea");
                }else if (rolecode.contains("LEADER")){
                    map.put("identity","leader");
                }else if (rolecode.contains("TEACHER")){
                    map.put("identity","teacher");
                }else {
                    map.put("identity","counsellor");
                }
                map.put("stuid",username);
                map.put("session_key",session_key);
                map.put("openId",openID);
                wxUser.setOpenID(openID);
                wxUser.setSession_key(session_key);
                wxUser.setUsername(username);
                redisTemplate.opsForHash().put("WXSESSIONKEY::"+username,"session_key", session_key);
                redisTemplate.expire("WXSESSIONKEY::"+username,66, TimeUnit.HOURS);
                return Result.success(map);
            }
        }
    }

    /**
     * 查询有没有openId
     *
     * @param code
     * @return
     */
    public Result queryOpenId(String code){
        String requestUrl = getWX_URL(code);
        //调用get方法
        JSONObject jsonObject = GetOpenidAndSessionKey(requestUrl);
        //解析返回值，对象解析成字符串
        String openID = jsonObject.getStr("openid");
        Map<String, Object> map = userMapper.queryOpenId(openID);
        Map<String, Object> openIdBySys = userMapper.queryOpenIdBySys(openID);
        if (map==null){
            if (openIdBySys==null){
                return Result.error("该微信号未被绑定！");
            }else {
                return Result.success(openIdBySys);
            }
        }else {
            map.put("identity","STUDENT,");
            return Result.success(map);
        }
    }

    /**
     * 比较 openid 判断当前用户保存在数据库中的是否一致
     * @param code
     * @param username
     * @return
     */
    public boolean contrastopenID(String code,String username){
        String requestUrl = getWX_URL(code);
        //调用get方法
        JSONObject jsonObject = GetOpenidAndSessionKey(requestUrl);
        //解析返回值，对象解析成字符串
        String openID = jsonObject.getStr("openid");
        String appid = userMapper.queryAppid(username);
        //先找是不是学生 ，是学生验证是否是一个微信号登录，如果不是 登录失败
        if (appid==null){
            //是老师 验证是否是自己的微信登录，不是退出
            String appidByTea = userMapper.queryAppidByTea(username);
            if (!appidByTea.equals(openID)){
                return false;
            }else {
                return true;
            }
        }else {
            if (appid.equals(openID)){
                return true;
            }else {
                return false;
            }
        }
    }

    /**
     * 原密码进行对比
     * @param username
     * @param pwd
     * @return
     */
    public Result queryPwdBysys(String username,String pwd){
        String md5AndSha = Encrypt.md5AndSha(pwd);
        String oldpwd = userMapper.queryPwd(username);
        if (md5AndSha.equals(oldpwd)){
            return Result.success("与原密码一致");
        }else {
            return Result.error("与原密码不一致");
        }
    }

    /**
     * 教师修改密码
     * @param username
     * @param pwd
     * @return
     */
    public Result updatePwdBysys(String username,String pwd){
        String md5AndSha = Encrypt.md5AndSha(pwd);
        userMapper.updatePwdBySys(md5AndSha,username);
        return Result.success("修改成功，请重新登录!");
    }

    /**
     * @Description 展示历史考勤信息图表
     * @Return
     * @Author dm
     **/
    @Override
    public Result queryHistories(String username, List<String> days) {
        Integer tid = userMapper.selectOne(Wrappers.<User>lambdaQuery().
                eq(User::getUsername, username)).getId();
        //查询该老师所带的所有班级
        List<String> allClass = classInfoMapper.selectAllClass(tid + "");
        Map<String, List<Integer>> data = new HashMap<>();
        for (String aClass : allClass) {
            List<Integer> datas = new ArrayList<>();
            for (int i = 0; i < days.size(); i++) {
                String day = days.get(i);
                List<AttendanceData> attendanceData = attendanceMapper.
                        queryHistories(tid + "", day, aClass);
                if (attendanceData == null || attendanceData.size() == 0 ) {
                    datas.add(0);
                } else if (attendanceData.size() == 1) {
                    datas.add(attendanceData.get(0).getArrivedcount() == null ? 0 :
                            Integer.parseInt(attendanceData.get(0).getArrivedcount()));
                } else {
                    datas.add(Integer.valueOf(attendanceData.get(0).getArrivedcount()));
                }
            }
            data.put(aClass, datas);
        }
        return Result.success(data);
    }

    /**
     * 小程序查询所有学期
     * @return
     */
    public List<String> queryTerms(){
        List<String> list = userMapper.queryTerms();
        return list;
    }
    /**
     * 小程序查询今天在哪个学期
     * @return
     */
    public Map<String, Object> queryTerm(String time){
        Map<String, Object> map = userMapper.queryTerm(time);
        return map;
    }

    /**
     * 小程序查询学生的考勤分数根据班级
     * @param name
     * @return
     */
    public List<Map<String,Object>> selectByCname(String name){
        List<Map<String, Object>> maps = studentInfoMapper.selectBystuInfoSum(name);
        List<Map<String, Object>> list = calculateScores(maps);
        return list;
    }

    public static List<Map<String, Object>> calculateScores(List<Map<String, Object>> maps) {
        List<Map<String, Object>> calculatedObjects = new ArrayList<>();
        // 遍历每个对象
        for (Map<String, Object> obj : maps) {
            // 旷课
            int absenteeism = ((Number) obj.get("absenteeism")).intValue();
            // 早退
            int leaveEarly = ((Number) obj.get("leave_early")).intValue();
            // 迟到
            int beLate = ((Number) obj.get("be_late")).intValue();
            int finalScore = 50;
            // 计算分数
            int totalScore = (leaveEarly + beLate) / 3 + absenteeism;
            finalScore = finalScore - totalScore;
            // 创建新的包含计算结果的对象
            Map<String, Object> calculatedObj = new HashMap<>(obj);
            calculatedObj.put("final_score", finalScore); // 添加总分数到新对象
            // 将新对象添加到结果列表
            calculatedObjects.add(calculatedObj);
        }
        // 按照 finalScore 属性升序排序
        Collections.sort(calculatedObjects, Comparator.comparingInt(obj -> (int) obj.get("final_score")));
        return calculatedObjects;
    }

}
